#include <Python.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>

void repeat(int fd1,int fd2)
{
    char buffer[1024];
    int len = 0,nfds=2,ret;
    int fd_in,fd_out;
    fd_set fds;
    struct timeval timeout={5,0};
    while(1){
        FD_ZERO(&fds);
        FD_SET(fd1,&fds); 
        FD_SET(fd2,&fds);
        nfds = fd1>fd2?fd1+1:fd2+1;
        ret = select(nfds,&fds,NULL,NULL,&timeout);
        if(ret==-1) return;
        else if (ret==0) continue;
        else break;
    }
    if( FD_ISSET(fd1,&fds) ) {
        fd_in = fd1;
        fd_out = fd2;
    } else
    if ( FD_ISSET(fd2,&fds) ) {
        fd_in = fd2;
        fd_out = fd1;
    }
    for(;;) {
        len = recv(fd_in,buffer,1024,0);
        if ( len==0 ){
            break;
        }
        send(fd_out,buffer,len,0);
    }
    shutdown(fd_in,SHUT_RDWR);
    shutdown(fd_out,SHUT_RDWR);
}

void repeat2(int fd_in,int fd_out)
{
    char buffer[1024];
    int len = 0;
    for(;;){
        len = recv(fd_in,buffer,1024,0);
        if ( len==0 ){
            break;
        }
        send(fd_out,buffer,len,0);
    }
    shutdown(fd_in,SHUT_RD);
    shutdown(fd_out,SHUT_WR);
}

//add wrapped function

static PyObject* wrap_repeat(PyObject *self, PyObject *args)
{
        //Convert the python input objects into C objects
    int fd1, fd2;
    if(!PyArg_ParseTuple(args, "ii", &fd1, &fd2)){
        return NULL;
        }
        //Call c function
    repeat(fd1,fd2);
        //wrap the result from c function to python object.
    return (PyObject*)Py_BuildValue("");
}

static PyObject* wrap_repeat2(PyObject *self, PyObject *args)
{
        //Convert the python input objects into C objects
    int fd1, fd2;
    if(!PyArg_ParseTuple(args, "ii", &fd1, &fd2)){
        return NULL;
        }
        //Call c function
    repeat2(fd1,fd2);
        //wrap the result from c function to python object.
    return (PyObject*)Py_BuildValue("");
}

//define the PyMethodDef methods
static PyMethodDef wrap_methods[] ={
    {"repeat", (PyCFunction)wrap_repeat, METH_VARARGS,NULL},
    {"repeat2", (PyCFunction)wrap_repeat2, METH_VARARGS,NULL},
    {NULL, NULL}
};
struct module_state {
    PyObject *error;
};
static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "repeator",
        NULL,
        sizeof(struct module_state),
        wrap_methods,
        NULL,
        NULL,
        NULL,
        NULL
};



//initilization function
PyMODINIT_FUNC PyInit_repeator(void)
{
    PyObject *module = PyModule_Create(&moduledef);
    return module;
}
